package me.shenfan.updateapp;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;

import java.io.File;
import java.io.Serializable;
import java.lang.ref.WeakReference;

import static me.shenfan.updateapp.UpdateHelper.Builder.DEFAULT_VERSION_NAME;

/**
 * Created by BlingBling on 16/9/19.
 */

public class UpdateHelper {
    private UpdateHelper.Builder mUpdate;
    private WeakReference<Activity> mWeakReference;
    private UpdateSharedPreferences mUpdateSharedPreferences;


    private MaterialDialog mUpdateProgressDialog;

    private UpdateHelper(UpdateHelper.Builder builder) {
        this.mUpdate = builder;
    }

    private Activity getActivity() {
        if (mWeakReference == null) {
            return null;
        }
        return mWeakReference.get();
    }

    /**
     * 是否已经下载
     *
     * @return
     */
    private boolean isDownload() {
        return TextUtils.equals(mUpdate.versionName, mUpdateSharedPreferences.getNewVersionName())
                && mUpdate.storeDir.exists()
                && mUpdate.storeDir.length() == mUpdateSharedPreferences.getFileLength();
    }

    /**
     * 退出
     */
    private void exitApp() {
        if (mOnUpdateCancelListener == null) {
            throw new NullPointerException("请在start(Activity)之前先调用setOnUpdateCancelListener(OnUpdateCancelListener)");
        }
        mOnUpdateCancelListener.exitApp();
    }

    /**
     * 显示新版本更新提示框
     */
    private void showUpdateDialog() {
        Activity activity = getActivity();
        if (activity == null || activity.isFinishing()) {
            return;
        }
        MaterialDialog.Builder dialogBuilder = new MaterialDialog.Builder(activity)
                .cancelable(false)
                .title(mUpdate.updateTitle)
                .content(mUpdate.updateContent)
                .positiveText("下载")
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        download();
                    }
                });
        if (mUpdate.isForceUpdate) {
            dialogBuilder.negativeText("退出");
            dialogBuilder.onNegative(new MaterialDialog.SingleButtonCallback() {
                @Override
                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                    exitApp();
                }
            });
        } else {
            dialogBuilder.negativeText("取消");
            if (!mUpdate.isManual && !DEFAULT_VERSION_NAME.equals(mUpdate.versionName)) {
                //不是手动点更新,并且设置了新版本号
                dialogBuilder.neutralText("忽略此版本");
                dialogBuilder.onNeutral(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        mUpdateSharedPreferences.setIgnoreVersionName(mUpdate.versionName);
                    }
                });
            }
        }
        dialogBuilder.show();
    }


    private void showUpdateProgressDialog(int progress) {
        final Activity activity = getActivity();
        if (activity == null || activity.isFinishing()) {
            return;
        }
        if (mUpdateProgressDialog == null) {
            MaterialDialog.Builder dialogBuilder = new MaterialDialog.Builder(activity)
                    .title("正在下载新版本")
                    .progress(false, 100);
            if (mUpdate.isForceUpdate) {
                dialogBuilder.cancelable(false);
            }
            mUpdateProgressDialog = dialogBuilder.build();
        }
        if (!mUpdateProgressDialog.isShowing()) {
            mUpdateProgressDialog.show();
        }
        mUpdateProgressDialog.setProgress(progress);
    }

    private void dismissUpdateProgressDialog() {
        if (mUpdateProgressDialog != null) {
            mUpdateProgressDialog.dismiss();
            mUpdateProgressDialog = null;
        }
    }

    private void showUpdateSuccessDialog(final File file) {
        Activity activity = getActivity();
        if (activity == null || activity.isFinishing()) {
            return;
        }
        MaterialDialog.Builder dialogBuilder = new MaterialDialog.Builder(activity)
                .autoDismiss(false)
                .cancelable(false)
                .title("升级提示")
                .content("新版本已经下载完成,点击按钮安装!")
                .positiveText("安装")
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        if (isDownload()) {
                            if (!mUpdate.isForceUpdate) {
                                dialog.dismiss();
                            }
                            installApk(file);
                        } else {
                            dialog.dismiss();
                            showUpdateFailDialog("文件损坏", "文件损坏,请重新下载!");
                        }
                    }
                });
        if (mUpdate.isForceUpdate) {
            dialogBuilder.negativeText("退出");
            dialogBuilder.onNegative(new MaterialDialog.SingleButtonCallback() {
                @Override
                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                    dialog.dismiss();
                    exitApp();
                }
            });
        } else {
            dialogBuilder.negativeText("取消");
            dialogBuilder.onNegative(new MaterialDialog.SingleButtonCallback() {
                @Override
                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                    dialog.dismiss();
                }
            });
        }
        dialogBuilder.show();
    }

    private void showUpdateFailDialog(String title, String content) {
        final Activity activity = getActivity();
        if (activity == null || activity.isFinishing()) {
            return;
        }
        MaterialDialog.Builder dialogBuilder = new MaterialDialog.Builder(activity)
                .cancelable(false)
                .title(title)
                .content(content)
                .positiveText("重新下载")
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        download();
                    }
                });
        if (mUpdate.isForceUpdate) {
            dialogBuilder.negativeText("退出");
            dialogBuilder.onNegative(new MaterialDialog.SingleButtonCallback() {
                @Override
                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                    exitApp();
                }
            });
        } else {
            dialogBuilder.negativeText("取消");
        }
        dialogBuilder.show();
    }

    private void download() {
        Activity activity = getActivity();
        if (activity == null) {
            return;
        }

        registerReceiver();
        showUpdateProgressDialog(0);

        Intent intent = new Intent(activity, UpdateService.class);
        intent.putExtra(UpdateService.EXTRA_UPDATE, mUpdate);
        activity.startService(intent);
    }

    private void installApk(File file) {
        Activity act = getActivity();
        if (act != null) {
            act.startActivity(UpdateUtil.installIntent(file.getAbsolutePath()));
        }
    }

    private void registerReceiver() {
        Activity activity = mWeakReference.get();
        if (activity == null) {
            return;
        }
        //注册广播
        IntentFilter intentFilter = new IntentFilter(UpdateService.ACTION_UPDATE);
        LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(activity);
        localBroadcastManager.registerReceiver(updateBroadcastReceiver, intentFilter);
    }

    /**
     * 注销广播
     */
    private void unregisterReceiver() {
        Activity activity = mWeakReference.get();
        if (activity == null) {
            return;
        }
        LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(activity);
        localBroadcastManager.unregisterReceiver(updateBroadcastReceiver);
    }

    /**
     * 广播接收器
     */
    private BroadcastReceiver updateBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (UpdateService.ACTION_UPDATE.equals(action)) {
                int status = intent.getIntExtra(UpdateService.EXTRA_UPDATE_STATUS, UpdateService.UPDATE_STATUS_START);
                switch (status) {
                    case UpdateService.UPDATE_STATUS_START://开始下载
                        showUpdateProgressDialog(0);
                        break;
                    case UpdateService.UPDATE_STATUS_PROGRESS://下载中
                        int progress = intent.getIntExtra(UpdateService.EXTRA_UPDATE_PROGRESS, 0);
                        if (mUpdateProgressDialog != null && mUpdateProgressDialog.isShowing()) {
                            mUpdateProgressDialog.setProgress(progress);
                        }
                        break;
                    case UpdateService.UPDATE_STATUS_SUCCESS://成功下载
                        unregisterReceiver();
                        dismissUpdateProgressDialog();
                        if (!mUpdate.isAutoInstall || mUpdate.isForceUpdate) {
                            String filePath = intent.getStringExtra(UpdateService.EXTRA_UPDATE_FILEPATH);
                            showUpdateSuccessDialog(new File(filePath));
                        }
                        break;
                    case UpdateService.UPDATE_STATUS_ERROR:// 下载失败
                        unregisterReceiver();
                        dismissUpdateProgressDialog();
                        String title;
                        String content;
                        switch (intent.getIntExtra(UpdateService.EXTRA_UPDATE_RESULT_CODE, -1)) {
                            case UpdateService.UPDATE_RESULT_ERROR_NETWORK:
                                title = "下载失败";
                                content = "网络异常,请检查网络是否正常再重新下载";
                                break;
                            case UpdateService.UPDATE_RESULT_ERROR_SERVER:
                                title = "下载失败";
                                content = "连接服务器失败,请重试";
                                break;
                            case UpdateService.UPDATE_RESULT_ERROR_SDCARD:
                                title = "下载失败";
                                content = "存储空间容量不足,请清理空间后重新下载";
                                break;
                            case UpdateService.UPDATE_RESULT_ERROR_OTHER:
                            default:
                                title = "下载失败";
                                content = "下载异常,请重新下载";
                                break;
                        }
                        showUpdateFailDialog(title, content);
                        break;
                }
            }
        }
    };

    private File getDownloadDir(Context context, File storeDir) {
        File downloadDir;
        if (TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)) {
            if (storeDir != null) {
                downloadDir = storeDir;
            } else {
                downloadDir = new File(context.getExternalCacheDir(), "update");
            }
        } else {
            downloadDir = new File(context.getCacheDir(), "update");
        }
        if (!downloadDir.exists()) {
            downloadDir.mkdirs();
        }
        return downloadDir;
    }

    private String getSaveFileName(String downloadUrl) {
        if (TextUtils.isEmpty(downloadUrl)) {
            return "update.apk";
        }
        return downloadUrl.substring(downloadUrl.lastIndexOf("/"));
    }

    public void start(Activity activity) {
        mWeakReference = new WeakReference<Activity>(activity);
        mUpdateSharedPreferences = new UpdateSharedPreferences(activity);
        File saveFile = new File(getDownloadDir(activity, mUpdate.storeDir), getSaveFileName(mUpdate.url));
        mUpdate.setStoreDir(saveFile);

        if (!mUpdate.isManual && TextUtils.equals(mUpdate.versionName, mUpdateSharedPreferences.getIgnoreVersionName())) {
            return;
        }

        if (isDownload()) {
            showUpdateSuccessDialog(saveFile);
        } else {
            showUpdateDialog();
        }
    }

    public void setOnUpdateCancelListener(OnUpdateCancelListener listener) {
        this.mOnUpdateCancelListener = listener;
    }

    private OnUpdateCancelListener mOnUpdateCancelListener;

    public interface OnUpdateCancelListener {
        void exitApp();
    }

    public static class Builder implements Serializable {
        //下载大小通知频率
        public static final int UPDATE_NUMBER_SIZE = 1;
        public static final int DEFAULT_RES_ID = -1;
        public static final String DEFAULT_VERSION_NAME = "0";

        protected String updateTitle;//更新标题
        protected String updateContent;//更细内容
        protected String versionName = DEFAULT_VERSION_NAME;//新版本名
        protected boolean isForceUpdate = false;//是否强制升级
        protected boolean isAutoInstall = true;//是否自动安装
        protected boolean isManual = true;//是否是手动点击更新(为false时如果设置了versionName会显示忽略此版本)

        protected String url;//apk下载地址
        protected File storeDir;//存储路径
        protected int updateProgress = UPDATE_NUMBER_SIZE;   //update notification progress when it add number
        protected int icoResId = DEFAULT_RES_ID;         //default app ico
        protected int icoSmallResId = DEFAULT_RES_ID;
        protected int downloadNotificationFlag;
        protected int downloadSuccessNotificationFlag;
        protected int downloadErrorNotificationFlag;

        public Builder(String url) {
            this.url = url;
        }

        public Builder setUpdateTitle(String updateTitle) {
            this.updateTitle = updateTitle;
            return this;
        }

        public Builder setUpdateContent(String updateContent) {
            this.updateContent = updateContent;
            return this;
        }

        public Builder setVersionName(String versionName) {
            if (!TextUtils.isEmpty(versionName)) {
                this.versionName = versionName;
            }
            return this;
        }

        public Builder setStoreDir(File storeDir) {
            this.storeDir = storeDir;
            return this;
        }

        public Builder setForceUpdate(boolean forceUpdate) {
            isForceUpdate = forceUpdate;
            return this;
        }

        public Builder setAutoInstall(boolean autoInstall) {
            isAutoInstall = autoInstall;
            return this;
        }

        public Builder setManual(boolean manual) {
            isManual = manual;
            return this;
        }

        public int getIcoResId() {
            return icoResId;
        }

        public Builder setIcoResId(int icoResId) {
            this.icoResId = icoResId;
            return this;
        }

        public int getIcoSmallResId() {
            return icoSmallResId;
        }

        public Builder setIcoSmallResId(int icoSmallResId) {
            this.icoSmallResId = icoSmallResId;
            return this;
        }

        public int getUpdateProgress() {
            return updateProgress;
        }

        public Builder setUpdateProgress(int updateProgress) {
            if (updateProgress < 1) {
                updateProgress = 1;
            }
            this.updateProgress = updateProgress;
            return this;
        }

        public File getStoreDir() {
            return storeDir;
        }

        public int getDownloadNotificationFlag() {
            return downloadNotificationFlag;
        }

        public Builder setDownloadNotificationFlag(int downloadNotificationFlag) {
            this.downloadNotificationFlag = downloadNotificationFlag;
            return this;
        }

        public int getDownloadSuccessNotificationFlag() {
            return downloadSuccessNotificationFlag;
        }

        public Builder setDownloadSuccessNotificationFlag(int downloadSuccessNotificationFlag) {
            this.downloadSuccessNotificationFlag = downloadSuccessNotificationFlag;
            return this;
        }

        public int getDownloadErrorNotificationFlag() {
            return downloadErrorNotificationFlag;
        }

        public Builder setDownloadErrorNotificationFlag(int downloadErrorNotificationFlag) {
            this.downloadErrorNotificationFlag = downloadErrorNotificationFlag;
            return this;
        }

        public UpdateHelper build() {
            if (TextUtils.isEmpty(updateTitle)) {
                updateTitle = "发现新版本";
            }
            if (TextUtils.isEmpty(updateContent)) {
                updateContent = "是否要下载新版本?";
            }

            return new UpdateHelper(this);
        }
    }
}
